package com.citywithincity.redis.models;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

public class RedisObjectModel<T> {
	private String mainKey;
	private Schema<T> schema;
	
	private RedisObjectGetter<T> getter;
	
	public RedisObjectModel(Class<T> clazz,String mainKey){
		this.mainKey = mainKey;
		schema =  RuntimeSchema.getSchema(clazz);
		
	}
	
	public void setGetter(RedisObjectGetter<T> getter){
		this.getter = getter;
	}
	
	private byte[] getKey(Object id){
		final String mainKey = this.mainKey;
		return new StringBuilder(mainKey).append(':').append(id).toString().getBytes();
	}
	
	
	public T get(Jedis jedis,Object id){
		final Schema<T> schema = this.schema;
		T message= schema.newMessage();
		ProtostuffIOUtil.mergeFrom(jedis.get(getKey(id)), message, schema);
		return message;
	}
	
	
	public List<T> getList(Jedis jedis,Collection<String> c){
		String[] keys = new String[c.size()];
		int index = 0;
		for (String bs : c) {
			keys[ index ++] = bs;
		}
		return getList(jedis,keys);
	}
	

	
	/**
	 * 获取list
	 * @param clazz
	 * @param keys
	 * @return
	 */
	public List<T> getList(Jedis jedis,String[] keys){
		//转化
		byte[][] bKeys = new byte[keys.length][];
		int index = 0;
		for (String string : keys) {
			bKeys[index++] = getKey(string);
		}
		List<byte[]> list = jedis.mget(bKeys);
		final Schema<T> schema = this.schema;
		List<T> result = new ArrayList<T>(list.size());
		
		for(int i=0 , c = list.size(); i < c; ++i){
			byte[] bytes = list.get(i);
			T data = null;
			if(bytes == null && getter!=null){
				synchronized (this  ) {
					data = getter.getObject(keys[i]);
					addOrUpdate(jedis, keys[i], data);
				}
			}else{
				try{
					data= schema.newMessage();
					ProtostuffIOUtil.mergeFrom(bytes, data, schema);
				}catch(Exception e){
					synchronized ( this ) {
						data = getter.getObject(keys[i]);
						addOrUpdate(jedis, keys[i], data);
					}
				}
				
			}
			result.add(data);
		}
		return result;
	}
	
	
	
	
	
	/**
	 * 修改一个
	 */
	public void addOrUpdate(Jedis jedis,Object id,T data){
		//增加一个key-value
		final Schema<T> schema = this.schema;
		byte[] bytes = ProtostuffIOUtil.toByteArray(data, schema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
		jedis.set(getKey(id), bytes);
	}

	/**
	 * 修改一个
	 */
	public void addOrUpdate(Pipeline jedis,Object id,T data){
		//增加一个key-value
		final Schema<T> schema = this.schema;
		byte[] bytes = ProtostuffIOUtil.toByteArray(data, schema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
		jedis.set(getKey(id), bytes);
	}
	/**
	 * 删除一个
	 */
	public void delete(Jedis jedis,Object id){
		jedis.del(getKey(id));
	}
}
